<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>SoundJS Tutorial: Preloading Audio</title>
    <link href="../_shared/tutorial.css" rel="stylesheet" type="text/css">
    <script src="../_shared/tutorial.js"></script>

    <!-- SyntaxHighlighter-->
    <script src="../_shared/SyntaxHighlighter/shCore.js"></script>
    <script src="../_shared/SyntaxHighlighter/shBrushJScript.js"></script>
    <script src="../_shared/SyntaxHighlighter/shBrushXml.js"></script>
    <link href="../_shared/SyntaxHighlighter/shCore.css" rel="stylesheet" type="text/css">
    <link href="../_shared/SyntaxHighlighter/shThemeCreateJS.css" rel="stylesheet" type="text/css">
</head>

<body onLoad="initTutorial();">
<article>
<header>
    <h1>SoundJS: Preloading Audio</h1>

    <p>
        <strong>Synopsis:</strong> Preload audio.<br>
        <strong>Topics:</strong> preload, registerSound, registerManifest, PreloadJS, manifest<br>
        <strong>Target:</strong> PreloadJS v0.4.1+
    </p>
</header>
<p class="highlight">
	This tutorial is part of the <a href="https://github.com/CreateJS/SoundJS/" target="_blank">SoundJS GitHub repository</a>.<br />
	Check out the repository for more tutorials and a handful of helpful samples.
</p>

<section>
    <header>
        <h2>SoundJS Basics</h2>
    </header>
    <p>
        Without CreateJS, most modern browsers do a great job of loading <em>enough</em> audio data to play back a sound
        continuously until the end using HTML tags. The <code>canplaythrough</code> event will fire when the buffer is
        full, and the sound will start. This is sufficient for a click-to-play sound, or for a background sound that
        can start whenever its ready - but in order to play on-demand audio for games, applications, and web sites,
        sounds must be preloaded first.
    </p>

    <p>
        There are a few different approaches to preloading, and this article provides some of the recommended patterns
        that can be used with SoundJS:
    </p>
    <ol>
        <li>Internal preloading capabilities in SoundJS</li>
        <li>Preloading audio using PreloadJS</li>
    </ol>

</section>

<section>
    <header>
        <h2>SoundJS Internal Preloading</h2>
    </header>
    <p>
        SoundJS includes the ability to internally preload audio.  This requires each sound to be
        "registered" with SoundJS, and it will immediately be preloaded for use.
    </p>
    <textarea class="brush: js;" readonly>
        createjs.Sound.registerSound({id:"soundId", src:"assets/music.mp3"});
    </textarea>

    <p>
        SoundJS will only preload audio that is supported, so if multiple formats are provided, only the one that the
        browser can play will be preloaded.
    </p>
    <textarea class="brush: js;" readonly>
        // Firefox and Opera will load "music.ogg"
        // Browsers with MP3 support will load "music.mp3"
		createjs.Sound.alternateExtensions = ["mp3"];
		createjs.Sound.registerSound({id:"soundId", src:"assets/music.ogg"});
    </textarea>

    <p>
        When each audio file is complete, the Sound class will fire off a <code>fileload</code> event. A
		<code>fileload</code> event is dispatched <strong>once</strong> for each audio file that has been registered.
        Multiple requests for the same audio source will fire the first time it is loaded, but for each instance that
        uses that source. The event contains the sound's <code>src</code> and <code>id</code> property, as well as a
        generic <code>data</code> property containing any associated data that was passed into the <code>registerSound</code>
        call.
    </p>

    <textarea class="brush: js; highlight:[1]" readonly>
        createjs.Sound.on("fileload", handleFileLoad);
        function handleFileLoad(event) {
        	// A sound has been preloaded.
        	console.log("Preloaded:", event.id, event.src);
        }
    </textarea>

    <p>
        Once you have registered sounds and they have finished loading, they can be played on-demand using the play
        call that passes in either the <code>src</code> or the <code>id</code>.
    </p>
    <textarea class="brush: js;" readonly>
        createjs.Sound.play("soundId");
    </textarea>

    <iframe src="internalPreloading.html" class="demo" longDesc="Simple internal preloading" width="100%"
            height="60px"></iframe>

    <p>
        A manifest of files can also be registered, but note that a <code>fileload</code> event will be fired for each
        sound - there is no "complete" event for internal preloading a manifest in SoundJS.
    </p>

    <textarea class="brush: js; highlight:[3,4,5,6]" readonly>
        createjs.Sound.on("fileload", handleFileLoad);
        createjs.Sound.alternateExtensions = ["mp3"];
        createjs.Sound.registerSounds(
			[{id:"music1", src:"music.mp3"},
        	{id:"music2", src:"music2.mp3"}]
        , "assets/");


		function handleFileLoad(event) {
        	// A sound has been preloaded. This will fire TWICE
        	console.log("Preloaded:", event.id, event.src);
        }
    </textarea>

    <p>
        This approach is great for quick demos, or applications that just need a little bit of audio. For larger
        projects, it is recommended to use PreloadJS to load audio.</p>
</section>

<section>
    <header>
        <h2>Preloading using PreloadJS</h2>
    </header>
    <p>
        PreloadJS is a CreateJS library that helps preload all sorts of content. Specific architecture has gone into how
        audio is preloaded, since it can not be simply downloaded and then retrieved from the browser cache like many
        html objects (such as images, scripts, svg, etc). For larger projects with many file types (or just a lot of
        files), PreloadJS is a better choice for loading audio.
    </p>
    <p>
        The <code>LoadQueue</code> class is the main interface for preloading content. Simply construct a LoadQueue, and
        then add a file, or manifest of files. The queue will dispatch events as the progress changes, files are loaded,
        or errors occur (plus <a
            href="http://www.createjs.com/Docs/PreloadJS/classes/AbstractLoader.html#event_complete" target="_blank">a
        few</a>
        <a href="http://www.createjs.com/Docs/PreloadJS/classes/LoadQueue.html#event_fileload" target="_blank">other
            events</a>).
    </p>

    <p>
        Here is a quick sample that loads some images:
    </p>

    <textarea class="brush: js;" readonly>
        var queue = new createjs.LoadQueue();
        queue.on("fileload", handleFileLoad);
        queue.on("complete", handleComplete);

        queue.loadFile({id:"myImage", src:"assets/image.jpg"});
        // OR
        queue.loadManifest([
        	{id:"myImage", src:"assets/image.jpg"},
        	{id:"myImage2", src:"assets/image2.jpg"}
        ]);
    </textarea>

    <p>
        Sounds require some special considerations though:
    </p>
    <ol>
        <li>PreloadJS doesn't know how to fallback to alternate file types if the original type is not supported</li>
        <li>PreloadJS has no way to determine <em>how</em> to load audio (xhr, tag, flash, etc)</li>
        <li>SoundJS requires some additional calls to register sounds properly</li>
    </ol>
    <p>
        To solve these (and other) problems, PreloadJS has a fairly simple plugin model, which provides the ability to
        pre-process files before they are loaded, or completely override how loading is done.
    </p>
    <p>
        SoundJS has already been built as a PreloadJS plugin, so it can just be installed, and audio loads will
        automatically be handled by SoundJS.
    </p>
    <textarea class="brush: js; highlight: [3]" readonly>
        var queue = new createjs.LoadQueue();
        createjs.Sound.alternateExtensions = ["mp3"];
        queue.installPlugin(createjs.Sound);
        queue.on("complete", handleComplete);
        queue.loadFile({id:"mySound", src:"assets/sound.ogg"});
    </textarea>

    <p>
        <strong>That's it!</strong> Now all preload requests that are of <code>type:"sound"</code> or have a
        supported file extension will be properly handled by SoundJS. All other aspects of preloading remain unchanged -
        the same events are dispatched, and initialized audio tags (for html audio) or data buffers (for web audio)
        will be available from PreloadJS. Sounds are also automatically registered with SoundJS.
    </p>
    <p>
        Sounds can now be played on-demand using the same code from the beginning of this tutorial:
    </p>
    <textarea class="brush: js;" readonly>
        createjs.Sound.play("mySound");
    </textarea>

    <iframe src="preloadjs.html" class="demo" longDesc="Loading using PreloadJS" width="100%"
            height="80px"></iframe>
</section>

<section>
    <header>
        <a name="FlashAudioPlugin"></a>
        <h2>Using Flash as a Fallback</h2>
    </header>
    <p>
        The FlashAudioPlugin is completely compatible with both internal and PreloadJS preloading. Follow the steps in the
        <a href="http://www.createjs.com/Docs/SoundJS/classes/FlashAudioPlugin.html" target="_blank">FlashAudioPlugin
            documentation</a> to set up the FlashAudioPlugin as a fallback (or primary playback plugin), and it will preload
        the same way the samples above describe.
    </p>
</section>

<section>
    <header>
        <h2>Tag loading vs XHR loading</h2>
    </header>
    <p>
        It is important to know <em>how</em> SoundJS loads audio, so it can be configured to work properly
        depending on the playback requirement (HTML tags vs WebAudio), or location of sound files (local, relative, or
        remote).
    </p>
    <p>
        SoundJS plays audio using a specific plugin depending on the capabilities. The available plugins are Web Audio,
        HTML Audio, and Flash. By default, SoundJS will attempt to use Web Audio playback (via the WebAudioPlugin), and
        then fall back to HTML audio when Web Audio is not supported. These playback modes will work in 90% of the
        current versions of <strong>modern</strong> browsers. (the big exception being Mobile Safari on iOS 5 and
        older).
    </p>
    <ol>
        <li>Web Audio requires a fully loaded data buffer, which can <strong>only</strong> be loaded using XHR
            (XMLHttpRequest).
        </li>
        <li>HTML Audio requires a sound tag, which has been loaded <em>enough</em> to play back, and can only be loaded
            using HTML audio tags. This is why loading using tags often appears to be faster, especially with large
            files
        </li>
        <li>Local and cross-domain loading can <strong>not</strong> use Web Audio due to cross-origin issues (CORS can
            be used to get around remote loading, but requires some server setup)
        </li>
    </ol>
    <p>
        The purpose of SoundJS is to provide a consistent playback engine, no matter what browser the end user has - so
        it will try and make the best determination it can on which plugin to use by testing browser capabilities. If
        there is no Web Audio support, or the user is loading local files, HTML audio will be used instead. Check out
        the <a href="#FlashAudioPlugin">section on Using Flash as a Fallback</a> for an additional fallback for older
        browsers.
    </p>
</section>

<section>
    <header>
        <h2>Related Links</h2>
    </header>
    <ol>
        <li>Download CreateJS from the <a href="http://code.createjs.com" target="_blank">Adobe CDN</a></li>
        <li>Get the SoundJS source code, including minified versions of SoundJS and FlashAudioPlugin from <a
                href="http://github.com/CreateJS/SoundJS/" target="_blank">GitHub</a>.
        </li>
        <li>Read more about SoundJS in the <a href="http://createjs.com/Docs/SoundJS" target="_blank">online docs</a>
            (also available in GitHub)
        </li>
        <li>Read more about PreloadJS in the <a href="http://createjs.com/Docs/PreloadJS" target="_blank">online
            docs</a> (also available in GitHub)
        </li>
    </ol>
</section>

</article>
</body>
</html>
